package com.bai.serviceOA.service.impl;


import com.bai.common.Result;
import com.bai.model.system.SysMenu;
import com.bai.model.system.SysRoleMenu;
import com.bai.model.vo.AssginMenuVo;
import com.bai.model.vo.MetaVo;
import com.bai.model.vo.RouterVo;
import com.bai.serviceOA.mapper.SysMenuMapper;
import com.bai.serviceOA.service.SysMenuService;
import com.bai.serviceOA.service.SysRoleMenuService;
import com.bai.serviceOA.util.MenuHelper;
import com.bai.serviceUtil.erro.BaiExcetion;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜单表 服务实现类
 * </p>
 *
 * @author bai
 * @since 2023-05-11
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    @Autowired
    private SysRoleMenuService sysRoleMenuService;

    /**
     * 菜单列表
     *
     * @return
     */
    @Override
    public List<SysMenu> findNodes() {
        //查询所有的菜单数据
        List<SysMenu> sysMenuList = baseMapper.selectList(null);
        //构建成树形结构(递归)
        List<SysMenu> resultList = MenuHelper.buildTree(sysMenuList);

        return resultList;
    }

    /**
     * 删除菜单
     *
     * @param id
     */
    @Override
    public void removeMwnuById(Long id) {
        //判断当前菜单是否有子菜单
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysMenu::getParentId, id);
        Integer count = baseMapper.selectCount(wrapper);
        if (count > 0) {
            throw new BaiExcetion(201, "菜单不能删除");
        }
        baseMapper.deleteById(id);
    }

    /**
     * 查询所有菜单和角色分配的菜单
     *
     * @param roleId
     * @return
     */
    @Override
    public List<SysMenu> findMenu(Long roleId) {
        //1、查询所有的菜单   status 1 可用的
        LambdaQueryWrapper<SysMenu> wrapperSysMenu = new LambdaQueryWrapper<>();
        wrapperSysMenu.eq(SysMenu::getStatus, 1);
        List<SysMenu> allSysMenuList = baseMapper.selectList(wrapperSysMenu);
        //2、根据角色id查询 角色菜单关系表 里 角色id对应的所有的菜单id
        LambdaQueryWrapper<SysRoleMenu> wrapperSysRoleMenu = new LambdaQueryWrapper<>();
        wrapperSysRoleMenu.eq(SysRoleMenu::getRoleId, roleId);
        List<SysRoleMenu> allSysRoleMenuList = sysRoleMenuService.list(wrapperSysRoleMenu);

        //3、根据获取的菜单id 获取对应的菜单对象
        List<Long> MenuIdList = allSysRoleMenuList.stream()
                                .map(c -> c.getMenuId()).collect(Collectors.toList());
        //3.1、拿着菜单id和所有菜单集合里面的id进行比较，如果相同封装
        allSysMenuList.stream().forEach(item -> {
            if (MenuIdList.contains(item.getId())) {
                item.setSelect(true);
            } else {
                item.setSelect(false);
            }
        });
        //4、返回规定格式的菜单列表
        List<SysMenu> sysMenuList = MenuHelper.buildTree(allSysMenuList);
        return sysMenuList;
    }

    /**
     * 角色分配菜单
     *
     * @param assginMenuVo
     */
    @Override
    public void doAssgin(AssginMenuVo assginMenuVo) {
        //1、根据角色id删除菜单角色里面的数据
        LambdaQueryWrapper<SysRoleMenu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysRoleMenu::getRoleId, assginMenuVo.getRoleId());
        sysRoleMenuService.remove(wrapper);
        //2、从参数里获取角色新分配菜单id列表，进行遍历，把每个id数据添加菜单角色表
        List<Long> menuIdList = assginMenuVo.getMenuIdList();
        for (Long menuId : menuIdList) {
            if (StringUtils.isEmpty(menuId)) {
                continue;
            }
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setMenuId(menuId);
            sysRoleMenu.setRoleId(assginMenuVo.getRoleId());
            sysRoleMenuService.save(sysRoleMenu);
        }
    }

    /**
     * 根据用户id获取用户可以操作的菜单列表
     *
     * @param userId
     * @return
     */
    @Override
    public List<RouterVo> findUserMenuListByUserId(Long userId) {
        //TODO: 1、判断当前用户是否是管理员
        List<SysMenu> sysMenuList = null;
        if (userId.longValue() == 1) {
            //1.1 如果世管理员查询所有菜单列表
            LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SysMenu::getStatus, 1);
            queryWrapper.orderByAsc(SysMenu::getSortValue);
            sysMenuList = baseMapper.selectList(queryWrapper);
        } else {
            //1.2 不是管理员根据id查询可以操作的菜单列表
            sysMenuList = baseMapper.findMenuListByUserId(userId);
        }
        //TODO: 把查询出来的数据列表结构构建成要求的数据结构
        List<SysMenu> sysMenuTreeList = MenuHelper.buildTree(sysMenuList);
        List<RouterVo> roulterList = this.buildRouter(sysMenuTreeList);
        return roulterList;
    }


    /**
     * 根据用户id获取用户可以操作的按钮列表
     *
     * @param userId
     * @return
     */
    @Override
    public List<String> findUserPermsByUserId(Long userId) {
        //TODO: 判断是否是管理员
        List<SysMenu> sysMenuList = null;
        if (userId.longValue() == 1) {
            //1.1 如果世管理员查询所有按钮列表
            //1.1 如果世管理员查询所有菜单列表
            LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SysMenu::getStatus, 1);
            sysMenuList = baseMapper.selectList(queryWrapper);
        } else {
            //1.2 不是管理员根据id查询可以操作的按钮列表
            //多表关联查询：用户角色关系表 角色菜单关系表  菜单表
            sysMenuList = baseMapper.findMenuListByUserId(userId);
        }
        //TODO: 查询出来的数据列表
        List<String> collect = sysMenuList.stream()
                .filter(item -> item.getType() == 2)
                .map(item -> item.getPerms())
                .collect(Collectors.toList());
        return collect;
    }


    //构建数据结构
    private List<RouterVo> buildRouter(List<SysMenu> menus) {
        //创建list集合用于存储数据
        List<RouterVo> routerVos = new ArrayList<>();
        //便利menus
        for (SysMenu menu : menus) {
            RouterVo routerVo = new RouterVo();
            routerVo.setHidden(false);
            routerVo.setAlwaysShow(false);
            routerVo.setPath(getRouterPath(menu));
            routerVo.setComponent(menu.getComponent());
            routerVo.setMeta(new MetaVo(menu.getName(), menu.getIcon()));
            //封装下一层数据
            List<SysMenu> children = menu.getChildren();
            if (menu.getType().intValue() == 1) {
                List<SysMenu> hiddenMenuList = children.stream()
                        .filter(item -> !StringUtils.isEmpty(item.getComponent()))
                        .collect(Collectors.toList());
                for (SysMenu hiddenMenu : hiddenMenuList) {
                    RouterVo hiddenRouter = new RouterVo();
                    hiddenRouter.setHidden(false);
                    hiddenRouter.setAlwaysShow(false);
                    hiddenRouter.setPath(getRouterPath(hiddenMenu));
                    hiddenRouter.setComponent(hiddenMenu.getComponent());
                    hiddenRouter.setMeta(new MetaVo(hiddenMenu.getName(), hiddenMenu.getIcon()));
                    routerVos.add(hiddenRouter);
                }
            } else {
                if (!CollectionUtils.isEmpty(children)) {
                    if (children.size() > 0) {
                        routerVo.setAlwaysShow(true);
                    }
                    //递归
                    routerVo.setChildren(buildRouter(children));
                }
            }
            routerVos.add(routerVo);
        }
        return routerVos;
    }

    /**
     * 获取路由地址
     *
     * @param menu
     * @return
     */
    public String getRouterPath(SysMenu menu) {
        String routerPath = "/" + menu.getPath();
        if (menu.getParentId().intValue() != 0) {
            routerPath = menu.getPath();
        }
        return routerPath;
    }
}
